
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'apis.dart';
import 'base_response_entity.dart';
import 'dio_utils.dart';
import 'error_handle.dart';
import 'intercept.dart';
import 'loading_util.dart';
import 'log_utils.dart';

typedef Success<T> = Function(T data);
typedef Fail = Function(int code, String msg);
typedef DownloadCompletion = Function();
typedef DownloadProgress = Function(int progress);

// 日志开关
const bool isOpenLog = true;
const bool isOpenAllLog = true;

class HttpUtils {
  /// dio main函数初始化
  static void initDio() {
    LogUtils.init();
    final List<Interceptor> interceptors = <Interceptor>[];

    /// 统一添加身份验证请求头
    interceptors.add(AuthInterceptor());

    /// 刷新Token
    interceptors.add(TokenInterceptor());

    /// 打印Log(生产模式去除)
    if (!LogUtils.inProduction && isOpenAllLog) {
      interceptors.add(LoggingInterceptor()); // 调试打开
    }
    configDio(
      baseUrl: APIs.apiPrefix,
      interceptors: interceptors,
    );
  }

  /// get 请求
  static void get<T>(
    String url,
    Map<String, dynamic>? params, {
    BuildContext? context,
    Success? success,
    Fail? fail,
  }) {
    request<T>(Method.get, url, params, context: context, success: success, fail: fail);
  }

  /// post 请求
  static void post<T>(
    String url,
    params, {
    BuildContext? context,
    Success? success,
    Fail? fail,
  }) {
    request<T>(Method.post, url, params, context : context, success: success, fail: fail);
  }

  /// _request 请求
  static void request<T>(
    Method method,
    String url,
    params, {
    BuildContext? context,
    Success? success,
    Fail? fail,
  }) {

    Object? data;
    Map<String, dynamic>? queryParameters;
    if (method == Method.get) {
      queryParameters = params;
    }
    if (method == Method.post) {
      data = params;
    }

    if (context != null) {
      LoadingUtils.showLoading(context);
    }
    DioUtils.instance.request(method, url, data: data, queryParameters: queryParameters, onSuccess: (result) {
      if (context != null) {
        LoadingUtils.hideLoading();
      }
      BaseResponseEntity<T> baseResponseEntity = BaseResponseEntity.fromJson(result);
      if (baseResponseEntity.code == ExceptionHandle.success) {
        success?.call(baseResponseEntity);
      } else {
        // 其他状态，弹出错误提示信息
        // JhProgressHUD.showText(result['msg']);
        fail?.call(baseResponseEntity.code, baseResponseEntity.message);
      }
    }, onError: (code, msg) {
      if (context != null) {
        LoadingUtils.hideLoading();
      }
      print("http error code:${code}  msg:${msg}");
      // JhProgressHUD.showError(msg);

      fail?.call(code, msg);
    });
  }

  static Future download(
      String url,
      String savePath, {
        Map<String, dynamic>? queryParams,
        CancelToken? cancelToken,
        DownloadProgress? onDownloadProgress,
        DownloadCompletion? onDownloadCompletion,
        Fail? onFail,
      }) async {
        try {
          return await DioUtils.instance.dio.download(
            url,
            savePath,
            queryParameters: queryParams,
            cancelToken: cancelToken,
            onReceiveProgress: (int received, int total){
              if(total != -1) {
                if(!(cancelToken?.isCancelled??false)) {
                    double downloadRatio = (received/total);
                    if(downloadRatio ==1) {
                      if(onDownloadCompletion != null) {
                        onDownloadCompletion();
                      }
                    }else{
                      if(onDownloadProgress != null) {
                        onDownloadProgress(((received/total)*100).toInt());
                      }
                    }
                }
              }else{
                onFail?.call(-1, '无法获取文件大小，下载失败！');
              }
            },
          );
        } on DioError catch (e) {
          if (CancelToken.isCancel(e)) {
            onFail?.call(-1, '下载已取消！');
          } else {
            onFail?.call(-1, e.toString());
          }
        } on Exception catch (e) {
          onFail?.call(-1, e.toString());
        }


  }


}
